import Vue from 'vue';
import axios from 'axios';

class TKmsConnection {
    constructor() {
        this.config = {
            clientId: ['c', (new Date()).getTime(), parseInt(100 * Math.random())].join(''),
            apiUrl: "https://localhost:31021",
            //apiUrl: "https://dq.hhdata.cn:31022",
            dbKey: "cock"
        };
        this.kmsConfig = null;
        this.kmsClient = null;
        this.cameras = [];
    };
    callApi(apiPath, ps, method) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var url = [me.config.apiUrl, apiPath].join('/');

                var data = (ps && ps != null) ? ps : {};
                if (method == "GET") {
                    axios.get(url, data).then(res => {
                        success(res);
                    })
                } else {
                    axios.post(url, data).then(res => {
                        success(res);
                    })
                }
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    query(key, ps) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var apiPath = "common/mysqldb/query";
                var postPs = {
                    appId: me.config.dbKey,
                    key: key,
                    psJson: JSON.stringify(ps)
                }
                me.callApi(apiPath, postPs, "POST").then(res => {
                    var result = res && res.data ? res.data.result : null;
                    success(result);
                })
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    getKmsConfig() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                if (me.kmsConfig && me.kmsConfig != null) {
                    success(me.kmsConfig);
                } else {
                    me.callApi("kms/v21/getConfig", {}).then(_config => {
                        me.kmsConfig = _config.data.data;
                        success(me.kmsConfig);
                    });
                }
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    getKmsClient() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                if (me.kmsClient && me.kmsClient != null) {
                    success(me.kmsClient);
                } else {
                    me.getKmsConfig().then(_ => {
                        kurentoClient(me.kmsConfig.kmsUrl, function(error, _client) {
                            me.kmsClient = _client;
                            if (error) {
                                console.log(error);
                                success(null)
                            } else {
                                _client.on('disconnect', function() {
                                    delete me['kmsClient'];
                                })
                                _client.getServerManager().then(_svr => {
                                    me.kmsSvr = _svr;
                                    return me.getDevices();
                                }).then(_devs => {
                                    me.cameras = _devs.videoinput;
                                    success(_client);
                                })

                            }
                        });
                    })
                }
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    getDevices() {
        var res = {};
        return new Promise((success, faild) => {
            try {
                navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(_ => {
                    return navigator.mediaDevices.enumerateDevices();
                }).then(function(devs) {
                    try {
                        for (var i = 0; i < devs.length; i++) {
                            var item = devs[i];
                            if (!res[item.kind]) {
                                res[item.kind] = []
                            }
                            res[item.kind].push(item);
                        }
                    } catch (er) {
                        console.log(er);
                    }
                    success(res);
                }).catch(function() {
                    success(res);
                });
            } catch (er) {
                console.log(er);
                success(res);
            }
        });
    };
    getChannel(channelCode, seatCodeList) {
        var me = this;
        var res = {};
        return new Promise((success, faild) => {
            try {
                var ps = {
                    channelCode: channelCode,
                    seatCodes: seatCodeList.join(",")
                };
                me.callApi("kms/v21/loadChannel", ps).then(channelInfo => {
                    var res = {
                        data: null,
                        channel: null,
                        success: false
                    };
                    try {
                        var flag = channelInfo && channelInfo.data && channelInfo.data.data &&
                            channelInfo.data.data.channel && channelInfo.data.data.channel.channelCode &&
                            channelInfo.data.data.channel.channelCode == channelCode;
                        if (flag) {
                            res.data = channelInfo.data.data;
                            me.getKmsClient().then(_ => {
                                return me.kmsClient.getMediaobjectById(res.data.channel.kmsId);
                            }).then(_pipe => {
                                res.channel = new TKmsChannel(me, channelCode);
                                res.channel.seats = res.data.seats;
                                res.channel.channel = res.data.channel;
                                res.channel.pipe = _pipe;
                                res.success = true;
                                success(res);
                            })
                        } else {
                            success(res);
                        }
                    } catch (ee) {
                        console.log(ee);
                        success(res);
                    }
                });
            } catch (er) {
                console.log(er);
                success(res);
            }
        });
    };
    createChannelEnd(channelCode, endCode) {
        var me = this;
        var res = {};
        return new Promise((success, faild) => {
            try {
                var ps = {
                    channelCode: channelCode,
                    endCode: endCode,
                    clientId: me.config.clientId
                };
                me.callApi("kms/v21/createChannelEnd", ps).then(endData => {
                    var res = {
                        data: null,
                        success: false
                    };
                    try {
                        var flag = endData && endData.data && endData.data.data &&
                            endData.data.data.endCode && endData.data.data.endCode == endCode;
                        if (flag) {
                            res.data = endData.data.data;
                            me.getKmsClient().then(_ => {
                                return me.kmsClient.getMediaobjectById(res.data.kmsId);
                            }).then(end => {
                                res.data.end = end;
                                res.success = true;
                                success(res);
                            })
                        } else {
                            success(res);
                        }
                    } catch (ee) {
                        console.log(ee);
                        success(res);
                    }
                });
            } catch (er) {
                console.log(er);
                success(res);
            }
        });
    };
    stopRecord(srcId, recFn) {
        var me = this;
        var res = {};
        return new Promise((success, faild) => {
            try {} catch (er) {
                console.log(er);
                success(res);
            }
        });
    };
    connectMedia(srcId, targetId, mediaType) {
        var me = this;
        return new Promise((success, faild) => {
            var res = {
                srcFlag: 0,
                target: 0,
                successFlag: 0
            };
            try {
                var ps = {
                    srcId,
                    targetId,
                    mediaType
                };
                me.callApi("kms/v21/connectMedia", ps).then(_res => {
                    try {
                        success(_res.data)
                    } catch (ee) {
                        console.log(ee);
                        success(res);
                    }
                });
            } catch (er) {
                console.log(er);
                success(res);
            }
        });
    };
    closeChannel(channelCode) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var ps = {
                    channelCode: channelCode
                };
                me.callApi("kms/v21/closeChannel", ps).then(_res => {
                    success()
                });
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };


    setCamera(peer, newDeviceId) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var currentDeviceId = peer.getLocalStream().getVideoTracks()[0].getSettings().deviceId;
                if (currentDeviceId != newDeviceId) {
                    var stream = peer.getLocalStream();
                    stream.getTracks().forEach(t => {
                        t.stop();
                    });
                }
                var mediaConstraints = peer.peerOption.mediaConstraints;
                mediaConstraints.video.deviceId = newDeviceId;
                navigator.mediaDevices.getUserMedia(mediaConstraints).then(function(stream) {
                    try {
                        peer.localVideo.srcObject = stream;
                        var streamTracks = {};
                        stream.getTracks().forEach(st => {
                            try {
                                streamTracks[st.kind] = st;
                            } catch (eer) {
                                console.log(eer);
                            }
                        });
                        peer.peerConnection.getSenders().forEach(_sender => {
                            try {
                                var kind = _sender.track.kind;
                                _sender.track.stop();
                                var stTrack = streamTracks[kind];
                                _sender.replaceTrack(stTrack);
                            } catch (eer) {
                                console.log(eer);
                            }
                        });
                    } catch (eSet) {
                        console.log(eSet);
                    }
                    try {
                        success();
                    } catch (eer) {
                        console.log(eer);
                    }
                }).catch(function(erSet) {
                    console.log(erSet);
                    try {
                        success();
                    } catch (eer) {
                        console.log(eer);
                    }
                });

            } catch (er) {
                console.log(er);
                try {
                    success();
                } catch (eer) {
                    console.log(eer);
                }
            }
        });
    };
    shareScreen(peer, width, height) {
        return new Promise((success, faild) => {
            try {
                var wWidth = width && width > 0 ? width : (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
                var wHeight = height && height > 0 ? height : (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight);
                var screenConstraints = { video: { width: { max: wWidth }, height: { max: wHeight } }, audio: true };
                var sender = null;
                if (navigator.mediaDevices.getDisplayMedia) {
                    navigator.mediaDevices.getDisplayMedia(screenConstraints).then(
                        function(stream) {
                            let videoTrack = stream.getVideoTracks()[0];
                            peer.localVideo.srcObject = stream;
                            sender = peer.peerConnection.getSenders().find(function(s) {
                                return s.track.kind == videoTrack.kind;
                            });
                            sender.track.stop();
                            sender.replaceTrack(videoTrack);
                            success();
                        }
                    )
                } else {
                    success();
                }
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    setPeerStream(peer, stream) {
        return new Promise((success, faild) => {
            try {
                var oldStream = peer.getLocalStream();
                if (oldStream && oldStream != null) {
                    oldStream.getTracks().forEach(t => {
                        t.stop();
                    });
                }
                try {
                    peer.localVideo.srcObject = stream;
                    var streamTracks = {};
                    stream.getTracks().forEach(st => {
                        try {
                            streamTracks[st.kind] = st;
                        } catch (eer) {
                            console.log(eer);
                        }
                    });
                    peer.peerConnection.getSenders().forEach(_sender => {
                        try {
                            var kind = _sender.track.kind;
                            _sender.track.stop();
                            var stTrack = streamTracks[kind];
                            _sender.replaceTrack(stTrack);
                        } catch (eer) {
                            console.log(eer);
                        }
                    });
                } catch (eSet) {
                    console.log(eSet);
                }
                try {
                    success();
                } catch (eer) {
                    console.log(eer);
                }
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    fullScreen(peer) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var element = peer.remoteVideo;
                me.fullScreenElement(element).then(_ => {
                    success();
                })
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    fullScreenElement(element) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                if (element.requestFullscreen) {
                    element.requestFullscreen();
                } else if (element.msRequestFullscreen) {
                    element.msRequestFullscreen();
                } else if (element.mozRequestFullScreen) {
                    element.mozRequestFullScreen();
                } else if (element.webkitRequestFullscreen) {
                    element.webkitRequestFullscreen();
                }
                success();
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
};
class TKmsChannel {
    constructor(connection, channelCode) {
        this.connection = connection;
        this.channelCode = channelCode;
        this.settings = {
            seatCodes: [],
            viewSettings: {}
        };
        this.channel = {};
        this.seats = {};
        this.pipe = null;
        this.views = {};
    };
    closeChannel() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                me.connection.closeChannel(me.channelCode);
                success();
            } catch (er) {
                console.log(er);
                success();
            }
        });
    }
    createView(viewCode, viewType, video, deviceId, seatCode, autoOpen) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var view = me.views[viewCode];
                var createKmsView = () => {
                    return new Promise((su, faild) => {
                        try {
                            var kmsView = new TKmsView(me, viewCode, viewType, video, deviceId, seatCode);
                            me.views[viewCode] = kmsView;
                            if (autoOpen) {
                                kmsView.open().then(_ => {
                                    success();
                                })
                            } else {
                                success(kmsView);
                            }
                        } catch (eer) {
                            console.log(eer);
                            su();
                        }
                    });
                };
                if (view && view != null) {
                    view.close().then(_ => {
                        createKmsView();
                    });
                } else {
                    createKmsView();
                }
            } catch (er) {
                console.log(er);
            }
        });
    };
};
class TKmsView {
    constructor(channel, viewCode, viewType, video, deviceId, seatCode) {
        this.channel = channel;
        this.viewCode = viewCode;
        this.viewType = viewType;
        this.video = video;
        this.peer = null;
        this.end = null;
        this.deviceId = deviceId;
        this.seatCode = seatCode;
        this.recorders = [];
    };
    open() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                me.createPeer().then(_peer => {
                    me.peer = _peer;
                    return me.channel.connection.createChannelEnd(me.channel.channelCode, me.viewCode);
                }).then(res => {
                    me.end = res.data.end;
                    return me.bindPeerEnd(me.peer, me.end);
                }).then(_ => {
                    var flag = me.seatCode && me.seatCode != null && me.seatCode != "" && me.channel.seats[me.seatCode] && me.channel.seats[me.seatCode].kmsId;
                    if (flag) {
                        var seatId = me.channel.seats[me.seatCode].kmsId;
                        var srcId = me.viewType == 's' ? me.end.id : seatId;
                        var targetId = me.viewType == 'r' ? me.end.id : seatId;
                        me.channel.connection.connectMedia(srcId, targetId, '').then(_ => {
                            success();
                        });
                    } else {
                        success();
                    }
                });
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    createPeer() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var peerFactories = {
                    s: kurentoUtils.WebRtcPeer.WebRtcPeerSendonly,
                    r: kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly,
                    sr: kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv
                };
                var createFatory = peerFactories[me.viewType == 's' ? 's' : 'r'];
                var options = {
                    configuration: me.channel.connection.kmsConfig.peerOptions.configuration,
                    mediaConstraints: me.channel.connection.kmsConfig.peerOptions.mediaConstraints,
                    localVideo: me.viewType == 's' ? me.video : null,
                    remoteVideo: me.viewType == 'r' ? me.video : null,
                };
                if (me.deviceId && me.deviceId != null && me.deviceId.length > 0) {
                    options.mediaConstraints.video.deviceId = me.deviceId;
                }
                var wrPeer = createFatory(options, function(erP) {
                    wrPeer.peerOption = options;
                    wrPeer.isScreen = false;
                    success(wrPeer);
                });
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    bindPeerEnd(peer, end) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                end.on('OnIceCandidate', function(event) {
                    var candidate = event.candidate;
                    peer.addIceCandidate(candidate);
                    console.log('candidate w->p', candidate);
                });
                peer.on('icecandidate', function(candidate) {
                    var iceCandidate = kurentoClient.register.complexTypes.IceCandidate(candidate);
                    end.addIceCandidate(iceCandidate);
                    console.log('candidate p->w', iceCandidate);
                });
                peer.generateOffer(function(er0, sdpOffer) {
                    end.processOffer(sdpOffer, function(er1, sdpAnswer) {
                        peer.processAnswer(sdpAnswer, function(er2) {
                            end.gatherCandidates(function(er3) {
                                success();
                            });
                        });
                    });
                });
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    close() {
        var me = this;
        return new Promise((success, faild) => {
            try {

            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    startRecord() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var recFn = ['rec', me.channelCode, me.viewCode + '_' + (new Date()).getTime].join('/') + '.webm';
                me.channel.connection.startRecord(me.end.id, recFn).then(recInfo => {

                    success(recInfo);
                })
            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
    stopRecord(recorderId) {
        var me = this;
        return new Promise((success, faild) => {
            try {

            } catch (er) {
                console.log(er);
                success();
            }
        });
    };
};

var kmsConnection = new TKmsConnection();
Vue.prototype.kmsConnection = kmsConnection;
Vue.prototype.kmsLib = {
    TKmsConnection,
    TKmsView
};